import { exec, spawn } from 'child_process';
import * as util from 'util';
import * as path from 'path';

const execAsync = util.promisify(exec);

// 使用实际的ADB安装路径
const adbCmd = 'D:\\software\\android_sdk\\platform-tools\\adb.exe';

// AutoJS脚本目录
const AUTOJS_SCRIPTS_DIR = '/sdcard/脚本/';

// AutoJS包名和Activity
const AUTOJS_PACKAGE = 'org.autojs.autojs';
const AUTOJS_ACTIVITY = 'org.autojs.autojs.ui.explorer.ExplorerActivity';

/**
 * 确保AutoJS脚本目录存在
 * @param deviceId 设备ID
 * @returns Promise<void>
 */
async function ensureScriptDirExists(deviceId: string): Promise<void> {
  try {
    // 检查目录是否存在
    const { stdout } = await execAsync(`${adbCmd} -s ${deviceId} shell "[ -d '${AUTOJS_SCRIPTS_DIR}' ] && echo 'exists' || echo 'not exists'"`);
    
    if (stdout.trim() === 'not exists') {
      // 创建目录
      await execAsync(`${adbCmd} -s ${deviceId} shell mkdir -p '${AUTOJS_SCRIPTS_DIR}'`);
      // 设置权限
      await execAsync(`${adbCmd} -s ${deviceId} shell chmod 755 '${AUTOJS_SCRIPTS_DIR}'`);
      console.log('已创建AutoJS脚本目录');
    }
  } catch (error) {
    console.error('确保脚本目录存在时出错:', error);
    throw new Error('创建AutoJS脚本目录失败');
  }
}

/**
 * 获取文件在设备上的完整路径
 * @param fileName 文件名
 * @returns 完整路径
 */
function getScriptPath(fileName: string): string {
  // 移除文件名中的特殊字符
  const safeFileName = fileName.replace(/[\\/:*?"<>|]/g, '_');
  return `${AUTOJS_SCRIPTS_DIR}${safeFileName}`;
}

/**
 * 将文件发送到设备
 * @param deviceId 设备ID
 * @param sourcePath 源文件路径
 * @param targetPath 目标路径（设备上的路径）
 * @param progressCallback 进度回调函数
 * @returns Promise<void>
 */
export async function sendFileToDevice(
  deviceId: string,
  sourcePath: string,
  fileName: string,
  progressCallback?: (progress: number) => void
): Promise<void> {
  try {
    // 确保脚本目录存在
    await ensureScriptDirExists(deviceId);

    // 获取目标路径
    const targetPath = getScriptPath(fileName);

    return new Promise((resolve, reject) => {
      // 确保源文件路径使用正确的路径分隔符
      const normalizedSourcePath = path.normalize(sourcePath);
      
      // 构建adb push命令
      const adbProcess = spawn(adbCmd, [
        '-s', deviceId,
        'push',
        normalizedSourcePath,
        targetPath
      ]);

      let lastProgress = 0;
      const progressRegex = /\[.*?(\d+)%\]/;

      adbProcess.stdout.on('data', (data) => {
        const output = data.toString();
        console.log('ADB Push输出:', output);
        
        // 解析进度信息
        const match = output.match(progressRegex);
        if (match) {
          const progress = parseInt(match[1], 10);
          if (progress !== lastProgress) {
            lastProgress = progress;
            progressCallback?.(progress);
          }
        }
      });

      adbProcess.stderr.on('data', (data) => {
        console.error('ADB Push错误:', data.toString());
      });

      adbProcess.on('close', (code) => {
        if (code === 0) {
          console.log('文件传输完成');
          progressCallback?.(100);
          resolve();
        } else {
          const error = new Error(`文件传输失败，退出码: ${code}`);
          console.error(error);
          reject(error);
        }
      });

      adbProcess.on('error', (error) => {
        console.error('ADB Push进程错误:', error);
        reject(error);
      });
    });
  } catch (error) {
    console.error('文件传输过程中出错:', error);
    throw error;
  }
}

export async function scanDevices(): Promise<{ id: string; model: string }[]> {
  console.log('开始扫描设备...');
  // 1. 获取设备ID列表
  const { stdout } = await execAsync(`${adbCmd} devices`);
  console.log('adb devices 输出:', stdout);
  
  const lines = stdout.split('\n').slice(1).filter(line => line.trim() && !line.includes('offline'));
  const ids = lines.map(line => line.split('\t')[0].trim()).filter(Boolean);
  
  console.log('找到设备IDs:', ids);
  if (ids.length === 0) return [];

  // 2. 查询每台设备的model
  const results: { id: string; model: string }[] = [];
  for (const id of ids) {
    try {
      const { stdout: modelOut } = await execAsync(`${adbCmd} -s ${id} shell getprop ro.product.model`);
      results.push({ id, model: modelOut.trim() });
    } catch (error) {
      console.error(`获取设备 ${id} 的型号失败:`, error);
      results.push({ id, model: 'Unknown' });
    }
  }
  
  console.log('扫描结果:', results);
  return results;
}

/**
 * 检查AutoJS是否已安装
 * @param deviceId 设备ID
 * @returns Promise<boolean>
 */
async function isAutoJsInstalled(deviceId: string): Promise<boolean> {
  try {
    const { stdout } = await execAsync(`${adbCmd} -s ${deviceId} shell pm list packages ${AUTOJS_PACKAGE}`);
    return stdout.includes(AUTOJS_PACKAGE);
  } catch (error) {
    console.error('检查AutoJS安装状态失败:', error);
    return false;
  }
}

/**
 * 启动AutoJS应用
 * @param deviceId 设备ID
 */
async function startAutoJs(deviceId: string): Promise<void> {
  try {
    await execAsync(`${adbCmd} -s ${deviceId} shell am start -n ${AUTOJS_PACKAGE}/${AUTOJS_ACTIVITY}`);
    // 等待应用启动
    await new Promise(resolve => setTimeout(resolve, 2000));
  } catch (error) {
    console.error('启动AutoJS失败:', error);
    throw new Error('启动AutoJS应用失败');
  }
}

/**
 * 执行AutoJS脚本
 * @param deviceId 设备ID
 * @param scriptContent 脚本内容
 * @returns Promise<void>
 */
export async function executeScript(deviceId: string, scriptContent: string): Promise<void> {
  try {
    // 检查AutoJS是否已安装
    const installed = await isAutoJsInstalled(deviceId);
    if (!installed) {
      throw new Error('设备上未安装AutoJS，请先安装AutoJS');
    }

    // 启动AutoJS
    await startAutoJs(deviceId);

    // 创建临时脚本文件
    const tempScriptPath = `${AUTOJS_SCRIPTS_DIR}temp_script_${Date.now()}.js`;
    const escapedContent = scriptContent.replace(/'/g, "'\\''");

    // 写入脚本内容
    await execAsync(`${adbCmd} -s ${deviceId} shell "echo '${escapedContent}' > ${tempScriptPath}"`);

    // 使用AutoJS执行脚本
    const result = await execAsync(`${adbCmd} -s ${deviceId} shell am broadcast -a org.autojs.autojs.action.IMPORT_SCRIPT --es path "${tempScriptPath}" --es execute "true"`);
    console.log('执行结果:', result.stdout);

    // 等待一段时间后删除临时脚本
    setTimeout(async () => {
      try {
        await execAsync(`${adbCmd} -s ${deviceId} shell rm ${tempScriptPath}`);
      } catch (error) {
        console.error('删除临时脚本失败:', error);
      }
    }, 5000);

  } catch (error) {
    console.error('执行脚本失败:', error);
    throw error;
  }
}

// 测试用例
if (require.main === module) {
  scanDevices().then(devices => {
    console.log('扫描到的设备:', devices);
  }).catch(err => {
    console.error('扫描失败:', err);
  });
} 